package ch.ethz.fcl.metrobuzz.algorithm.network.all_simple_paths;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ch.ethz.fcl.metrobuzz.algorithm.network.Path;
import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Node;

/**
 * A origin-destination pair may have certain possibility passing through an
 * edge
 * 
 * @author Zeng Wei
 * @email zeng@arch.ethz.ch
 * 
 */
public class EdgeODPossibility {
	private MBData data;
	private Map<EdgeOD, Float> edgeODPossMap;

	public EdgeODPossibility(MBData data) {
		this.data = data;
		edgeODPossMap = new HashMap<EdgeOD, Float>();
	}

	public void generateEdgeODPoss() {
		long startTime = System.currentTimeMillis();

		List<Node> MRTNodes = data.getScene().getMRTNodes();
		for (Node origin : MRTNodes) {
			for (Node destin : MRTNodes)
				if (!origin.equals(destin)) {
					List<Path> paths = AllSimplePaths.getAllSimplePaths(data,
							origin, destin);
					List<Float> possList = AllSimplePaths
							.pathPossibility(paths);

					for (int k = 0; k < paths.size(); k++) {
						List<Node> nodeList = paths.get(k).getPath();
						for (int i = 0; i < nodeList.size() - 1; i++) {
							for (int j = i + 1; j < nodeList.size(); j++) {
								Node n1 = nodeList.get(i);
								Node n2 = nodeList.get(j);

								EdgeOD edgeOD = new EdgeOD(n1, n2, origin,
										destin);

								// if (n1.getId().equals("EW24/NS1")
								// && n2.getId().equals("EW23")
								// && origin.getId().equals("EW27")
								// && destin.getId().equals("EW15"))
								// System.out.println("path : "
								// + paths.get(k).toString()
								// + " poss " + possList.get(k));

								Float poss = edgeODPossMap.get(edgeOD);
								if (poss == null) {
									edgeODPossMap.put(edgeOD, possList.get(k));
								} else {
									// if (n1.getId().equals("EW24/NS1")
									// && n2.getId().equals("EW23")
									// && origin.getId().equals("NS2")
									// && destin.getId().equals("EW4/CG0"))
									// System.out.println("previous poss " +
									// poss
									// + " new poss " + possList.get(k));

									edgeODPossMap.put(edgeOD, possList.get(k)
											+ poss);
								}
							}
						}
					}
				}
		}

		System.out.println("Time cost to generate edge OD possibility "
				+ (System.currentTimeMillis() - startTime) / 1000.0f);
	}

	public float getEdgeODPoss(Node edgeN1, Node edgeN2, Node origin,
			Node destin) {
		EdgeOD edgeOD = new EdgeOD(edgeN1, edgeN2, origin, destin);
		Float poss = edgeODPossMap.get(edgeOD);
		if (poss == null) {
			return 0;
		} else {
			return poss;
		}
	}

	class EdgeOD {
		Node edgeN1;
		Node edgeN2;
		Node origin;
		Node destin;

		public EdgeOD(Node edgeN1, Node edgeN2, Node origin, Node destin) {
			this.edgeN1 = edgeN1;
			this.edgeN2 = edgeN2;
			this.origin = origin;
			this.destin = destin;
		}

		@Override
		public boolean equals(Object o) {
			if (!(o instanceof EdgeOD))
				return false;

			EdgeOD edgeOD = (EdgeOD) o;
			if (edgeOD.toString().equals(toString()))
				return true;

			return false;
		}

		@Override
		public int hashCode() {
			String id = toString();
			return id.hashCode();
		}

		@Override
		public String toString() {
			String id = edgeN1.getId() + " " + edgeN2.getId() + " "
					+ origin.getId() + " " + destin.getId();
			return id;
		}
	}
}
